package logic

import (
	"common/biz"
	"common/logs"
	"context"
	"core/models/entity"
	"core/repo"
	"core/service"
	"framework/msError"
	"framework/remote"
	"hall/component/proto"
	hall "hall/models/response"
	"sync"
	"time"
)

type ProductionManager struct {
	sync.RWMutex
	timerOutput       map[uint]*time.Timer
	productionService *service.ProductionService
	manager           *Manager
}

func (m *ProductionManager) run() {
	//重启任务，生产定时完成
	logs.Warn("初始化重启定时任务-生产-定时完成")
	go m.restartScheduleExecute()
}

func (m *ProductionManager) ProductionStart(ctx context.Context, uid uint, id uint, session *remote.Session) (*hall.ProductionList, *msError.Error) {
	//1.检查是否可以生产
	data := m.productionService.RoleProductionInfo(ctx, uid, id)
	if data == nil || data.ID == 0 {
		logs.Error("[productionHandler]用户%d ProductionStart err:槽位不存在", uid)
		return nil, biz.ProductionNotOpen
	}
	if data.Status {
		logs.Error("[productionHandler]用户%d ProductionStart err:槽位已生产", uid)
		return nil, biz.ProductionAlreadyProduction
	}
	if data.CardWID == 0 {
		logs.Error("[productionHandler]用户%d ProductionStart err:未安装卡片", uid)
		return nil, biz.ProductionNotInstallCard
	}
	//2.修改为生产中
	info, mInfo, err := m.productionService.ProductionStart(ctx, data)
	if err != nil {
		return nil, err
	}
	//3.添加到定时任务
	times := mInfo.EndTime - time.Now().Unix()
	go m.scheduleExecute(times, mInfo, session)
	return info, nil
}

func (m *ProductionManager) scheduleExecute(times int64, info *entity.ProductionOutput, session *remote.Session) {
	m.Lock()
	defer m.Unlock()
	timer, ok := m.timerOutput[info.ProductionID]
	if ok {
		timer.Stop()
	}
	//times = 10
	timer = time.AfterFunc(time.Duration(times)*time.Second, func() {
		timer.Stop()
		ctx := context.TODO()
		data, err := m.productionService.ProductionEnd(ctx, info)
		if err != nil {
			logs.Error("%v", err)
			return
		}
		if session != nil {
			m.manager.ServerMessagePush([]string{session.GetUid()}, proto.ProductionNotifyData(data), session)
		}
		delete(m.timerOutput, info.ProductionID)
	})
}

func (m *ProductionManager) restartScheduleExecute() {
	ctx := context.TODO()
	output := m.productionService.MongoOutputAll(ctx)
	for k, v := range *output {
		data := v
		var times int64
		if time.Now().Unix() >= data.EndTime {
			//已超时，未处理
			times = int64(k)
		} else {
			times = data.EndTime - time.Now().Unix()
		}
		go m.scheduleExecute(times, &v, nil)
	}
}

func NewProductionManager(r *repo.Manager) *ProductionManager {
	p := &ProductionManager{
		timerOutput:       make(map[uint]*time.Timer),
		productionService: service.NewProductionService(r),
		manager:           NewManager(),
	}
	p.run()
	return p
}
